/*
 * Project: Sudoku Solver
 * File: grid.h
 *
 * Copyright (C) 2009 Daniel Meekins
 * Contact: dmeekins - gmail
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef GRID_H
#define GRID_H

#include "cell.h"

#define ROWS   CELL_MAX_NUM
#define COLS   CELL_MAX_NUM
#define G_ROWS 3
#define G_COLS 3

struct grid
{
    cell_t *cells[ROWS][COLS];
};

typedef struct grid grid_t;

#define GRID_SUB_ROW(row) ( (row * G_ROWS) / ROWS )
#define GRID_SUB_COL(col) ( (col * G_COLS) / COLS )

#define GRID_GLOBAL_ROW(gr,r) ( (gr * G_ROWS) + r )
#define GRID_GLOBAL_COL(gc,c) ( (gc * G_COLS) + c )


/*
 * Allocates space for a new grid, initializing the cells' possible numbers to
 * the corresponding numbers in the passed nums matrix. If a number in nums is
 * 0, then all the possible numbers will be set. If nums is NULL, a grid of
 * blank cells is made. Returns a pointer to the created grid.
 */
grid_t *grid_new(uint32_t nums[ROWS][COLS]);

/*
 * 
 */
int grid_check(grid_t *g);

#define GRID_CHECK(g)                                      \
    if(grid_check(g) == -1)                                \
    {                                                      \
        printf("grid_check, %s:%d\n", __FILE__, __LINE__); \
        grid_print_full(g);                                \
        exit(-1);                                          \
    }

/*
 * Goes through each row, column, and subgrid and updates the possible numbers
 * for each cell by seeing what is left in each row, column, or subgrid.
 */
void grid_update(grid_t *g);

/*
 * Returns the cell located at the global position in the grid by the passed
 * row and column number.
 */
cell_t *grid_cell_at(grid_t *g, uint32_t r, uint32_t c);

/*
 * Returns the cell located at the local position (sub_c,sub_r) inside the
 * subgrid at (grid_c, grid_r).
 */
cell_t *grid_local_cell_at(grid_t *g, uint32_t grid_r, uint32_t grid_c,
                           uint32_t sub_r, uint32_t sub_c);

/*
 * Returns the number of the cell located at the position in the grid.
 */
uint32_t grid_num_at(grid_t *g, uint32_t r, uint32_t c);

/*
 * Sets the number of the cell located at the global (c,r) position.
 */
void grid_set_cell_num(grid_t *g, uint32_t num, uint32_t r, uint32_t c);

/*
 * Sets the passed number of the cell located in the subgrid (gc,gr) at
 * position (c,r).
 */
void grid_set_local_cell_num(grid_t *g, uint32_t num, 
                             uint32_t gr, uint32_t gc, uint32_t r, uint32_t c);

/*
 * Returns the number of cells in the subgrid at location (gc,gr) that are
 * solved.
 */
int grid_sub_num_solved(grid_t *g, uint32_t gr, uint32_t gc);

/*
 * Returns 1 of the cell at the global location (gc,gr) in the grid is solved,
 * and 0 otherwise.
 */
int grid_issolved(grid_t *g);

/*
 * Prints the grid is a viewable format.
 */
void grid_print(grid_t *g);

/*
 * Prints the internal data of each cell in the grid.
 */
void grid_print_full(grid_t *g);

/*
 * Frees the space that was used up by the grid structure.
 */
void grid_free(grid_t *g);

#endif /* GRID_H */
